package com.dwd.hrm.controller;

import com.dwd.hrm.doc.CourseDoc;
import com.dwd.hrm.highlight.HighlightResultMapper;
import com.dwd.hrm.query.CourseDocQuery;
import com.dwd.hrm.repository.CourseElasticsearchRepository;
import com.dwd.hrm.util.AjaxResult;
import com.dwd.hrm.util.PageList;
import com.dwd.hrm.vo.AggVo;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @Description: TODO
 * @Author 汶狄
 * @Date 2021/3/8 15:54
 * @Version 1.0
 */
@RestController
@RequestMapping("/esSearch")
public class SearchController {
    @Autowired
    private CourseElasticsearchRepository courseElasticsearchRepository;
    @Autowired
    private HighlightResultMapper highlightResultMapper;
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;


    /**
     * 添加到es索引库中
     *
     * @param courseDoc
     * @return
     */
    @PostMapping("/addOrUpdate")
    @PreAuthorize("hasAuthority('esSearch:addOrUpdate')")
    public AjaxResult addOrUpdate(@RequestBody CourseDoc courseDoc) {
        courseElasticsearchRepository.save(courseDoc);
        return AjaxResult.me();
    }


    /**
     * 从es库删除索引
     *
     * @param id
     * @return
     */
    @DeleteMapping("/delete/{id}")
    public AjaxResult deleteCourse(@PathVariable("id") Long id) {
        courseElasticsearchRepository.deleteById(id);
        return AjaxResult.me();
    }

    /**
     * 全部
     *
     * @param courseDocs
     * @return
     */
    @PostMapping("/addAll")
    public AjaxResult addAll(@RequestBody List<CourseDoc> courseDocs) {
        courseElasticsearchRepository.saveAll(courseDocs);
        return AjaxResult.me();
    }

    /**
     * 查询
     *
     * @param courseDocQuery
     * @return
     */
    @PostMapping("/queryCourses")
//    @PreAuthorize("hasAuthority('esSearch:queryCourses')")
    public PageList<CourseDoc> queryCourses(@RequestBody CourseDocQuery courseDocQuery) {
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        //聚合
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("tenantNameAgg").field("tenantName").order(Terms.Order.count(false)).size(20));
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("couseTypeAgg").field("courseTypeName").order(Terms.Order.count(false)).size(20));
        //等于1或者null才高亮
        if (courseDocQuery.getHighlight().intValue() == 1 || courseDocQuery.getHighlight() == null) {
            //设置高亮显示
            HighlightBuilder.Field field = new HighlightBuilder.Field("name").preTags("<font style='color:red'><b>").postTags("</b></font>");
            // 名字高亮
            nativeSearchQueryBuilder.withHighlightFields(field);
        }
        //DSL查询
        //匹配
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        if (StringUtils.isNotBlank(courseDocQuery.getKeyword())) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("name", courseDocQuery.getKeyword()));
//                    .must(QueryBuilders.matchQuery("tenantName", courseDocQuery.getKeyword()));
        }
        //过滤
        //获取最小价格
        if (courseDocQuery.getPriceMin() != null) {
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(courseDocQuery.getPriceMin()));
        }
        if (courseDocQuery.getPriceMax() != null) {
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(courseDocQuery.getPriceMax()));
        }
        //查询
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        //分页
        nativeSearchQueryBuilder.withPageable(PageRequest.of(courseDocQuery.getPage() - 1, courseDocQuery.getRows()));
        //按照排序类型
        String sortType = courseDocQuery.getSortType();
        SortOrder sortOrder = null;
        if (StringUtils.isNotBlank(sortType)) {
            sortOrder = sortType.equals(SortOrder.DESC) ? SortOrder.DESC : SortOrder.ASC;
        }
        //获取前端排序字段   没有以价格排序
//        String sortField = StringUtils.isBlank(courseDocQuery.getSortField()) ? "price" : courseDocQuery.getSortField();
        //排序字段
//        FieldSortBuilder fieldSortBuilder = new FieldSortBuilder(sortField);
        //排序
//        nativeSearchQueryBuilder.withSort(fieldSortBuilder.order(sortOrder));
//        Page<CourseDoc> page = courseElasticsearchRepository.search(nativeSearchQueryBuilder.build());
        AggregatedPage<CourseDoc> page = elasticsearchTemplate.queryForPage(nativeSearchQueryBuilder.build(), CourseDoc.class, highlightResultMapper);
        //map用来装聚合结果
        Map<String, List<AggVo>> map = new HashMap<>(16);
        //获取聚合结果 renantNameAgg
        StringTerms tenantNameAgg = (StringTerms) page.getAggregation("tenantNameAgg");
        //里面是每一个对象
        List<StringTerms.Bucket> buckets = tenantNameAgg.getBuckets();
        ArrayList<AggVo> aggVos = new ArrayList<>();
        buckets.forEach(bucket -> {
            AggVo aggVo = new AggVo();
            aggVo.setKey(bucket.getKeyAsString()).setCount(bucket.getDocCount());
            //添加到集合
            aggVos.add(aggVo);
        });

        map.put("tenantNameAgg", aggVos);
        StringTerms couseTypeAgg = (StringTerms) page.getAggregation("couseTypeAgg");
        //里面是每一个对象
        List<StringTerms.Bucket> buckets1 = couseTypeAgg.getBuckets();
        ArrayList<AggVo> couseaggVos = new ArrayList<>();
        buckets1.forEach(bucket -> {
            AggVo aggVo = new AggVo();
            aggVo.setKey(bucket.getKeyAsString()).setCount(bucket.getDocCount());
            //添加到集合
            couseaggVos.add(aggVo);
        });
        map.put("couseTypeAgg", couseaggVos);
        return new PageList<>(page.getTotalElements(), page.getContent(), map);
    }
}

